package com.jiefeng.manager.service.springsecurity;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import java.io.IOException;


/**
 * Created by WuZhiqi on 2016/7/3.
 */
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{

    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    /**
     * Method that is actually called by the filter chain. Simply delegates to
     * the {@link #invoke(FilterInvocation)} method.
     *
     * @param request
     *            the servlet request
     * @param response
     *            the servlet response
     * @param chain
     *            the filter chain
     *
     * @throws IOException
     *             if the filter chain fails
     * @throws ServletException
     *             if the filter chain fails
     */
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {

        System.out.println("***********自定义的授权拦截器正在被执行*********");
        System.out.println("*********************************************************");
        System.out.println("请求登录的用户名为：********************"+request.getAttribute("j_username"));
        System.out.println("请求登录的密码为：********************"+request.getAttribute("j_password"));
        System.out.println("请求登录的密码为：********************"+request.getAttribute("j_password"));
        System.out.println("请求alwaysremember为：*************************"+request.getAttribute("_spring_security_remember_me"));

        FilterInvocation fi = new FilterInvocation(request, response, chain);//采用该对象可以从request和respond中提取出很多的HTTP信息
        invoke(fi);
    }

    public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public Class<? extends Object> getSecureObjectClass() {
        return FilterInvocation.class;
    }
    /**
     *
     * @param fi
     * @throws IOException
     * @throws ServletException
     * 最核心的代码就是下面的invoke()方法中的InterceptorStatusToken token = super.beforeInvocation(fi);
     * 这一句，即在执行doFilter之前，进行权限的检查，而具体的实现已经交给accessDecisionManager了，下文中会讲述。
     */
    public void invoke(FilterInvocation fi) throws IOException,
            ServletException {

        System.out.println("***********自定义的filter正在被执行*****自定义的授权拦截器正在被执行****");
        InterceptorStatusToken token = super.beforeInvocation(fi);  //在执行doFilter之前，进行权限的检查，而具体的实现已经交给accessDecisionManager了
        //beforeInvocation(fi)进行事前评估，检查用户的身份是否符合目标资源设定的权限要求
//	        System.out.println("***********自定义的授权拦截器正在被执行****决策后返回的访问资源配置权限，InterceptorStatusToken.getAttributes()"+token.getAttributes().size());
//	    	System.out.println("*******以下为该请求的URL："+fi.getRequestUrl()+"所有的权限****");
//	    	Object[] attributes=token.getAttributes().toArray();
//	    	for(int i=0;i<token.getAttributes().size();i++)
//	    	{
//	    		System.out.println("*******attributes["+i+"]:"+(ConfigAttribute)attributes[i]);
//
//	    	}
        System.out.println("*******以上为我们为访问资源配置的权限*********自定义的授权拦截器正在被执行****");
        try {
            //调用目标WEB资源
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            //事后审查，确认当前用户是否有权操控返回结果包含的所有领域对象
            super.afterInvocation(token, null);
        }
    }


    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }

    public void setSecurityMetadataSource(
            FilterInvocationSecurityMetadataSource newSource) {
        this.securityMetadataSource = newSource;
    }

    public void destroy() {
    }

    public void init(FilterConfig arg0) throws ServletException {
    }


}

